package test;


import java.util.ArrayList;
import java.util.Iterator;

import com.duniptech.engine.core.modeling.Atomic;
import com.duniptech.engine.core.modeling.Message;
import com.duniptech.engine.core.modeling.api.IMessage;

public class Transducer extends Atomic {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	// Ports
	public static final String arrived = "arrived";
	public static final String solved = "solved";
	public static final String out = "out";
	
	// State
	protected ArrayList<Job> jobsArrived;
	protected ArrayList<Job> jobsSolved;
	protected double observationTime;
	protected double total_ta;
	protected double clock;
	
	public Transducer(String name, double observationTime) {
		super(name);
		addInport(Transducer.arrived);
		addInport(Transducer.solved);
		addOutport(Transducer.out);
		jobsArrived = new ArrayList<Job>();
		jobsSolved = new ArrayList<Job>();
		this.observationTime = observationTime;
		setSigma(observationTime);
		total_ta = 0;
		clock = 0;
	}
	
	public Transducer() {
		this("Transducer", 100.0);
	}

	public void deltint() {
		//System.out.println("Start: " + this.getClass().getName() + "::deltint()");
		clock = clock + getSigma();
		double throughput;
		double avg_ta_time;
		if(!jobsSolved.isEmpty()) {
			avg_ta_time = total_ta / jobsSolved.size();
			if (clock > 0.0) throughput = jobsSolved.size() / clock;
			else throughput = 0.0;
		}
		else {
			avg_ta_time = 0.0;
			throughput = 0.0;
		}
		System.out.println("End time: " + clock);
		System.out.println("jobs arrived : " + jobsArrived.size ());
		System.out.println("jobs solved : " + jobsSolved.size());
		System.out.println("AVERAGE TA = " + avg_ta_time);
		System.out.println("THROUGHPUT = " + throughput);
		setSigma(INFINITY);
		//System.out.println("End: " + this.getClass().getName() + "::deltint()");
	}

	public void deltext(double e, IMessage x) {
		//System.out.println("Start: " + this.getClass().getName() + "::deltext()");
		setSigma(getSigma() - e);
		clock = clock + e;
		Iterator<?> itr = null;
		
		itr = x.getValuesOnPort(Transducer.arrived).iterator();
		while(itr.hasNext()) {
			Job job = (Job)itr.next();
			System.out.println("Start job " + job.getName() + " @ t = " + clock);
			job.setTime(clock);
			jobsArrived.add(job);
		}

		itr = x.getValuesOnPort(Transducer.solved).iterator();
		while(itr.hasNext()) {
			Job job = (Job)itr.next();
			total_ta += (clock - job.getTime());
			System.out.println("Finish job " + job.getName() + " @ t = " + clock);
			job.setTime(clock);
			jobsSolved.add(job);
		}
		//System.out.println("End: " + this.getClass().getName() + "::deltext()");
	}


	public IMessage lambda() {
		//System.out.println("Start: " + this.getClass().getName() + "::lambda()");
		Job job = new Job("null");
		IMessage msg = new Message();
		msg.add(Transducer.out, job);
		//System.out.println("End: " + this.getClass().getName() + "::lambda()");
		return msg;
	}

}
